package com.starsray.dynamic.ds.event;

import com.baomidou.dynamic.datasource.event.DataSourceInitEvent;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.starsray.dynamic.ds.config.DsEncryptorConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jasypt.properties.PropertyValueEncryptionUtils;
import org.jasypt.util.text.BasicTextEncryptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;

@Slf4j
@Primary
@Component
public class DsEncryptorEvent implements DataSourceInitEvent {

    private static DsEncryptorConfig encryptorConfig;

    @Autowired
    public void setConfig(DsEncryptorConfig config) {
        DsEncryptorEvent.encryptorConfig = config;
    }

    private static String PASSWORD;

    private static final BasicTextEncryptor basicTextEncryptor = new BasicTextEncryptor();

    static {
        String systemProperty = System.getProperty("jasypt.encryptor.password");
        if (StringUtils.isNotBlank(systemProperty)) {
            PASSWORD = systemProperty;
        } else {
            if (encryptorConfig.isBootstrap()) {
                PASSWORD = encryptorConfig.getPassword();
            } else {
                PASSWORD = "DEFAULT";
            }
        }
        basicTextEncryptor.setPassword(PASSWORD);
    }

    @Override
    public void beforeCreate(DataSourceProperty dataSourceProperty) {
        // 跳过配置文件主数据源
        if (!dataSourceProperty.getPoolName().equals("master")) {
            String username = dataSourceProperty.getUsername();
            String password = dataSourceProperty.getPassword();
            dataSourceProperty.setUsername(decrypt(username));
            dataSourceProperty.setPassword(decrypt(password));
        }
    }

    @Override
    public void afterCreate(DataSource dataSource) {

    }

    private String decrypt(String ciphertext) {
        log.info("encrypt text ：{}", ciphertext);
        try {
            if (PropertyValueEncryptionUtils.isEncryptedValue(ciphertext)) {
                return PropertyValueEncryptionUtils.decrypt(ciphertext, basicTextEncryptor);
            } else {
                return ciphertext;
            }
        } catch (Exception e) {
            throw new RuntimeException("decrypt error : " + ciphertext);
        }
    }
}
